package data;

import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;

import com.leapmotion.leap.Controller;
import com.leapmotion.leap.Frame;
import com.leapmotion.leap.Gesture;
import com.leapmotion.leap.GestureList;
import com.leapmotion.leap.Listener;

public class LeapMotionListener extends Listener {
	private List<Gesture.Type> gestureTypes;
	private int bufferSize = 1;
	private Queue<Gesture> mostRecentGestures = new LinkedBlockingQueue<Gesture>(bufferSize);
	private boolean bufferChanged = false;
	
	public LeapMotionListener(List<Gesture.Type> gestureTypes) {
		this.gestureTypes = gestureTypes;
	}
	
	public void onInit(Controller controller) {
        System.out.println("Initialized");
    }

    public void onConnect(Controller controller) {
        System.out.println("Connected");
        
        for (Gesture.Type type : gestureTypes) {
        	controller.enableGesture(type);
        }
    }

    public void onDisconnect(Controller controller) {
        //Note: not dispatched when running in a debugger.
        System.out.println("Disconnected");
    }

    public void onExit(Controller controller) {
        System.out.println("Exited");
    }
    
    public void onFrame(Controller controller) {
    	Frame frame = controller.frame();
    	
    	GestureList gestures = frame.gestures();

		for (Gesture gesture : gestures) {
			
			boolean updated = false;
			/* Try and update a gesture in progress */
			for (Gesture bufferedGesture : mostRecentGestures) {
				if (bufferedGesture.id() == gesture.id()) {
					mostRecentGestures.remove(bufferedGesture);
					mostRecentGestures.add(gesture);
					updated = true;
					//System.out.println("Updated gesture " + gesture.id()); //TODO
					/* Gesture in progress is not a relevant change in our context */
					this.bufferChanged = false;
					break;
				}
			}
			
			if (!updated) {
				/* Remove the oldest gesture and replace with the newer */
				if (mostRecentGestures.size() == bufferSize) {
					mostRecentGestures.poll();
					mostRecentGestures.add(gesture);
					this.bufferChanged = true;

				} else {
					mostRecentGestures.add(gesture);
					this.bufferChanged = true;
				}
			}
		}
	}
    
    public boolean hasBufferChanged() {
    	return this.bufferChanged;
    }
    
    public List<Gesture> mostRecentGestures() {
    	/* Reset dirty bit */
    	this.bufferChanged = false;
    	return new ArrayList<Gesture>(mostRecentGestures);
    }
    
}
